package com.mjh.zhujianju.excel;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.OfficeXmlFileException;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.web.multipart.MultipartFile;

import com.livew.framework.utils.XTStringUtils;

public class ExcelUtil {
    /**
     * 获得excel文件数据
     * @param file excel文件
     * @param sheetInfo 初始化信息
     * @return Map {sheet1:List}
     * @throws Exception Exception
     */
    @SuppressWarnings({ "unchecked", "rawtypes" })
    public static Map getExcel(MultipartFile file, SheetInfo sheetInfo) throws Exception {
        Map<String, String> columnsMap = new HashMap<String, String>();
        //用于存储Excel根据指定规则读取的所有内容
        Map excelInfo = new HashMap();
        // 列验证表达式map
        Map<String, ERegExp> validateMap = new HashMap<>();
        List<String> errMsg = new ArrayList<String>();

        // 错误总数
        int errNum = 0;
        // 限制错误提示数
        int errLimit = 10;

        for (ColumnProperty o : sheetInfo.getColumnProperties()) {
            columnsMap.put(o.getColumnName(), o.getFieldName());
            validateMap.put(o.getColumnName(), o.getRegExp());
        }
        Workbook book = null;
        InputStream in = null;
        try {
            in = file.getInputStream();
            book = new HSSFWorkbook(in);
        } catch (OfficeXmlFileException e) {
            in = file.getInputStream();
            book = new XSSFWorkbook(in);
        }

        // 获得工作表数量
        int sheetNum = book.getNumberOfSheets();
        // 循环所有的工作表，读取里面的数据
        boolean key=true;
        for (int sheetIndex = 0; sheetIndex < sheetNum && key; sheetIndex++) {
            // 获得当前工作表对象
            Sheet sheet = book.getSheetAt(sheetIndex);
            // 如果与sheet名称不匹配，跳过此处循环
            if(!sheet.getSheetName().equals(sheetInfo.getSheetName())){
                continue;
            }

            // 用于存储所工作表中的数据内容
            List sheetList = new ArrayList();
            // 获取当前表格的行数
            int rows = sheet.getLastRowNum();
            // 获取当前表格的列数
            int columns = sheet.getRow(0).getLastCellNum();
            // 获得当前工作表标题内容
            List<String> titleList = new ArrayList<String>();
            // 循环每一行中的每一个单元格，读取单元格内的值
            Row titleRow = sheet.getRow(SheetInfo.DEFAILT_TITLE_INDEX);
            for (int jj = 0; jj < columns; jj++) {
                titleList.add(titleRow.getCell(jj).getStringCellValue());
            }
            // 验证表头
            for (ColumnProperty o : sheetInfo.getColumnProperties()) {
                // 如果Excel表格中的表头缺少该字段
                if (!titleList.contains(o.getColumnName())) {
                    errMsg.add("上传文件格式错误！");
                    key=false;
                    break;
                }
            }
            // 开始循环每一行，读取每一行的值,从标题下面一行开始读取
            for (int i = SheetInfo.DEFAILT_TITLE_INDEX + 1; i <= rows && key; i++) {
                Map rowMap = new HashMap();
                Row dataRow = sheet.getRow(i);
                //判断是否为空行
                if(ExcelUtil.isRowEmpty(dataRow)){
                    continue;
                }
                // 循环每一行中的每一个单元格，读取单元格内的值
                for (int j = 0; j < columns; j++) {
                    String columnTitle = titleList.get(j);
                    if ("".equals(columnTitle)) {
                        continue;
                    } else {
                        Cell cell = dataRow.getCell(j);
                        String value = "";
                        if (null != cell) {
                            cell.setCellType(Cell.CELL_TYPE_STRING);
                            value = cell + "";
                        }
                        // 单元列对应的entity属性名
                        String columnMapping = columnsMap.get(columnTitle);
                        if(StringUtils.isEmpty(columnMapping)){
                            continue;
                        }
                        String validateReg = "";
                        String validateRegMsg = "";
                        if (null != validateMap.get(columnTitle)) {
                            // 验证正则表达式
                            ERegExp eum = validateMap.get(columnTitle);
                            validateReg = eum.getValue();
                            validateRegMsg = eum.getText();
                        }
                        if (XTStringUtils.isNotEmpty(validateReg)) {
                            if (value.matches(validateReg)) {
                                rowMap.put(columnMapping, value);
                            } else {
                                errNum++;
                                if (errNum <= errLimit) {
                                    errMsg.add("第" + Integer.valueOf(i+1) + "行：【" + columnTitle + "】数据为:'" + value.trim() + "' 不匹配！【" + validateRegMsg + "】</br>\n");
                                }
                            }
                        } else {
                            rowMap.put(columnMapping, value);
                        }
                    }
                }
                sheetList.add(rowMap);
            }
            excelInfo.put(sheet.getSheetName(), sheetList);
        }
        in.close();
        if (errMsg.size() > 0) {
            if (errNum > errLimit) {
                errMsg.add("您导入的数据模板格式错误过多(共" + errNum + "个)，请仔细检查模板数据是否正确！");
            }
            throw new Exception(errMsg.toString().replaceAll("\\[|\\]", ""));
        }
        return excelInfo;
    }



    public static boolean isRowEmpty(Row row) {
        for (int c = row.getFirstCellNum(); c < row.getLastCellNum(); c++) {
            Cell cell = row.getCell(c);
            if (cell != null && cell.getCellType() != Cell.CELL_TYPE_BLANK){
                return false;
            }
        }
        return true;
    }

}
